﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Text;
using System.IO.Ports;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using ZedGraph;
using 串口助手;

namespace Project
{
    public partial class Form1 : Form
    {
        // Make up some data points based on the Sine function
        PointPairList list = new PointPairList();

        private int EndXAbs = 0, EndYAbs = 0;       //Interpolation end point coordainate abs
        private int EndX = 0, EndY = 0;             //Interpolation end point coordainate
        private int NowX = 0, NowY = 0;             //Interpolation point coordainate

        private int Com_status = 0;                 //Serial port status

        private List<byte> receiveBuff = new List<byte>();
        private byte[] sendBuff = new byte[5];
        private byte[] data_Receive = new byte[5];
        //private int Rxd_Num = 0;
        private const int Rxd_Len = 5; 

        //Data frame timeout detection
        //private const int OverTimeSet = 5;
        //private int OverTime = 0;

        //Determine whether Update interpplation information 
        private bool updata_Status = false;

        //Update interpplation information
        private int StepNo = 0;
        private string Lastres = "0";

        public Form1()
        {
            InitializeComponent();
            //Control.CheckForIllegalCrossThreadCalls = false;
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            Port_cbb.Items.Clear();
            string[] serialPortName = SerialPort.GetPortNames();
            foreach (string name in serialPortName)
            {
                Port_cbb.Items.Add(name);
            }
            InitControl();
        }
        private void InitControl()
        {
            this.Size = new Size(1450, 1000);
            
            this.Port_cbb.SelectedIndex = 1;
            this.Baud_cbb.SelectedIndex = 1;
            this.Data_cbb.SelectedIndex = 1;
            this.Check_cbb.SelectedIndex = 0;
            this.Stop_cbb.SelectedIndex = 0;

            this.SPC_X.Text = 0.ToString();
            this.SPC_Y.Text = 0.ToString();
            this.EPC_X.Text = 7.ToString();
            this.EPC_Y.Text = 7.ToString();

            this.Coordinate_COM.Text = Port_cbb.Text;
        }

        private void Switch_btn_Click(object sender, EventArgs e)
        {
            try
            {
                if (serialPort1.IsOpen == false)
                {
                    serialPort1.PortName = this.Port_cbb.Text;
                    serialPort1.BaudRate = Convert.ToInt32(Baud_cbb.Text);
                    serialPort1.DataBits = Convert.ToInt32(Data_cbb.Text);
                    switch (Check_cbb.SelectedIndex)
                    {
                        case 0:
                            serialPort1.Parity = Parity.None;
                            break;
                        case 1:
                            serialPort1.Parity = Parity.Odd;
                            break;
                        case 2:
                            serialPort1.Parity = Parity.Even;
                            break;
                        default:
                            serialPort1.Parity = Parity.None;
                            break;
                    }
                    switch (Stop_cbb.SelectedIndex)
                    {
                        case 0:
                            serialPort1.StopBits = StopBits.One;
                            break;
                        case 1:
                            serialPort1.StopBits = StopBits.OnePointFive;
                            break;
                        case 2:
                            serialPort1.StopBits = StopBits.Two;
                            break;
                        default:
                            serialPort1.StopBits = StopBits.One;
                            break;
                    }
                    serialPort1.Open();
                    Com_status = 1;
                }
                else
                {
                    serialPort1.Close();
                    Com_status = 2;
                }
            }
            catch (Exception ex)
            {

                MessageBox.Show(ex.ToString() + serialPort1.PortName.ToString());
            }

            switch (Com_status)
            {
                case 1:
                    Switch_btn.BackColor = Color.Green;
                    Switch_btn.Text = "关闭串口";
                    Status_label.BackColor = Color.Green;
                    Status_label.Text = serialPort1.PortName.ToString() + " is opened";
                    MessageBox.Show("SerialPort " + serialPort1.PortName + " is open^-^");
                    break;
                case 2:
                    Switch_btn.BackColor = Color.Red;
                    Switch_btn.Text = "打开串口";
                    Status_label.BackColor = Color.Red;
                    Status_label.Text = serialPort1.PortName.ToString() + " is closed";
                    MessageBox.Show("SerialPort " + serialPort1.PortName + " is close^-^");
                    break;
                default:
                    break;

            }
        }

        private void Interpolation_btn_Click(object sender, EventArgs e)
        {
            bool Coordinate = false;
            bool info_Ready = false;

            NowX = 0;
            NowY = 0;
            StepNo = 0;
            receiveBuff.Clear();
            ReceSend_rtb.Text = "";
            Interpolation_rtb.Text = "";

            if (serialPort1.IsOpen)
            {
                try
                {
                    EndX = Convert.ToInt32(EPC_X.Text);
                    EndY = Convert.ToInt32(EPC_Y.Text);

                    EndXAbs = Math.Abs(EndX);
                    EndYAbs = Math.Abs(EndY);

                    if ((EndXAbs >= 1) && (EndXAbs <= 9)
                        && (EndYAbs >= 1) && (EndYAbs <= 9))
                        Coordinate = true;
                    else
                        MessageBox.Show("终点坐标已超出规定范围！！！");
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.ToString());
                }

            }
            else
            {
                MessageBox.Show("Error!\r\nPlease open the serial port first.");
            }
            
            
            if (Coordinate == true)
            {
                //sendBuff[0] = Convert.ToByte('s');
                
                if(EndX > 0) sendBuff[0] = Convert.ToByte('+');
                else sendBuff[0] = Convert.ToByte('-');
                sendBuff[1] = Convert.ToByte(EndXAbs + 0x30);

                if (EndY > 0) sendBuff[2] = Convert.ToByte('+');
                else sendBuff[2] = Convert.ToByte('-');
                sendBuff[3] = Convert.ToByte(EndYAbs + 0x30);

                //sendBuff[5] = Convert.ToByte('e');
                info_Ready = true;
            }
            if (info_Ready == true)
            {
                serialPort1.Write(sendBuff, 0, 4);

                ReceSend_rtb.AppendText("Transmit:");

                ReceSend_rtb.AppendText(Encoding.GetEncoding("gb2312").GetString(sendBuff).Replace("\0", "\00"));
                ReceSend_rtb.AppendText("\r\n");

                zedGraphInit();
            }

        }

        private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            
            byte[] dataTemp = new byte[serialPort1.BytesToRead];
            serialPort1.Read(dataTemp, 0, dataTemp.Length);
            receiveBuff.AddRange(dataTemp); 


            this.Invoke(new EventHandler(delegate
            {
                //if (OverTime >= OverTimeSet)
                //{
                //    ReceSend_rtb.AppendText("Received:");
                //}
                //OverTime = 0;

                if (receiveBuff.ToArray().Length >= Rxd_Len)
                {
                    data_Receive = receiveBuff.ToArray();
                    if ((data_Receive[0] == '+') || (data_Receive[0] == '-'))
                        if ((data_Receive[1] == '+') || (data_Receive[1] == '-'))
                            if ((data_Receive[2] == 'x') || (data_Receive[2] == 'y'))
                                if ((data_Receive[3] == '+') || (data_Receive[3] == '-'))
                                    if ((data_Receive[4] >= '0') || (data_Receive[4] <= '9'))
                                        updata_Status = true;

                    if (updata_Status == false)
                    {
                        MessageBox.Show("ERROR\r\nSerial port communication is not performed according to the agreed protocol.");
                    }

                    ReceSend_rtb.AppendText("Received:");
                    if (!HEX_chb.Checked)
                    {
                        string str = Encoding.GetEncoding("gb2312").GetString(receiveBuff.ToArray());
                        //str = str.Replace("\0", "\00");
                        ReceSend_rtb.AppendText(str);
                        ReceSend_rtb.AppendText("\r\n");
                        //  Interpolation_trb.AppendText(Encoding.GetEncoding("gb2312").GetString(dataTemp).replace("\0","\00"));
                    }
                    else
                    {
                        ReceSend_rtb.AppendText(Transform.ToHexString(receiveBuff.ToArray(), " "));
                    }
                    ReceSend_rtb.SelectionStart = ReceSend_rtb.Text.Length; // 将光标移至末尾
                    ReceSend_rtb.ScrollToCaret(); // 滚动到光标位置

                    if (updata_Status == true)
                    {
                        Updata_Information();
                    }
                    receiveBuff.Clear();
                }

                

            }));

            //string Datareceive = serialPort1.ReadExisting();
            //if (Datareceive != null)
            //{
            //    Interpolation_trb.AppendText(Datareceive);
            //}
        }

        private void HEX_chb_CheckedChanged(object sender, EventArgs e)
        {
            //if (ReceSend_rtb.Text == "") return;
            //if (HEX_chb.Checked)
            //{
            //    ReceSend_rtb.Text = Transform.ToHexString(receiveBuff.ToArray());
            //}
            //else 
            //{
            //    ReceSend_rtb.Text = Encoding.GetEncoding("gb2312").GetString(receiveBuff.ToArray()).Replace("\0", "\00");
            //}
        }

        private void Clear_btn_Click(object sender, EventArgs e)
        {
            receiveBuff.Clear();
            ReceSend_rtb.Text = "";
        }

        private void Updata_Information()
        {
            updata_Status = false;
            
            StepNo++;
            if (StepNo <= (EndXAbs + EndYAbs))
            {
                string liststr = StepNo.ToString();
                if (StepNo < 10)
                    liststr += "       ";
                else
                    liststr += "      ";
                if (data_Receive[0] == '+')
                    liststr += "F≥0        ";
                else
                    liststr += "F＜0        ";

                liststr += ((char)data_Receive[1]).ToString() + ((char)data_Receive[2]).ToString() + "       ";
                liststr += "F=" + Lastres;
                Lastres = ((char)data_Receive[4]).ToString();

                if (data_Receive[0] == '+')
                    liststr += "-" + EndXAbs.ToString() + "=";
                else
                    liststr += "+" + EndYAbs.ToString() + "=";
                if (data_Receive[3] == '-')
                    liststr += '-';
                liststr += Convert.ToChar(data_Receive[4]);

                if (data_Receive[3] == '-')
                    liststr += "     ";
                else
                    liststr += "      ";
                liststr += (EndXAbs + EndYAbs - StepNo).ToString() + "\r\n";

                Interpolation_rtb.AppendText(liststr);

                //update the Coordinate system Information
                if ((data_Receive[1] == '+') && (data_Receive[2] == 'x'))
                    NowX += 1;
                else if ((data_Receive[1] == '-') && (data_Receive[2] == 'x'))
                    NowX -= 1;
                else if ((data_Receive[1] == '+') && (data_Receive[2] == 'y'))
                    NowY += 1;
                else if ((data_Receive[1] == '-') && (data_Receive[2] == 'y'))
                    NowY -= 1;

                list.Add(NowX, NowY);
                // Make sure the Graph gets redrawn
                zedGraphControl1.Invalidate();
            }
            else 
            {
                MessageBox.Show("ERROR!\r\nThe number of frames sent by serial port exceeds the total steps.");
            }

        }

        private void zedGraphInit()
        {
            string Quadrant_Title = "0";
            int Quadrant = 0;
            
            Interpolation_rtb.Text = "步数   偏差判别   坐标进给   偏差计算   终点判断\r\n";
            Interpolation_rtb.Text += "                             F=0          " + (EndXAbs + EndYAbs).ToString() + "\r\n";
            // Get a reference to the GraphPane instance in the ZedGraphControl
            GraphPane myPane = zedGraphControl1.GraphPane;
            myPane.CurveList.Clear();
            list.Clear();

            if ((EndX > 0) && (EndY > 0))
            {
                Quadrant = 1;
                Quadrant_Title = "第一象限插补";
            }
            else if ((EndX < 0) && (EndY > 0))
            {
                Quadrant = 2;
                Quadrant_Title = "第二象限插补";
            }
            else if ((EndX < 0) && (EndY < 0))
            {
                Quadrant = 3;
                Quadrant_Title = "第三象限插补";
            }
            else if ((EndX > 0) && (EndY < 0))
            {
                Quadrant = 4;
                Quadrant_Title = "第四象限插补";
            }
            // Set the titles and axis labels
            myPane.Title.Text = Quadrant_Title;
            myPane.XAxis.Title.Text = "XAxis";
            myPane.YAxis.Title.Text = "YAxis";

            // Show the x axis grid
            myPane.XAxis.MajorGrid.IsVisible = true;
            myPane.YAxis.MajorGrid.IsVisible = true;
            // Fill the axis background with a gradient
            myPane.Chart.Fill = new Fill(Color.White, Color.LightGray, 45.0f);

            int AxisScale = (EndXAbs > EndYAbs) ? (EndXAbs+1) : (EndYAbs+1);
            int XaxisMin = 0, XaxisMax = 0;
            int YaxisMin = 0, YaxisMax = 0;

            switch (Quadrant)
            {
                case 1:
                    XaxisMin = -1; XaxisMax = AxisScale;
                    YaxisMin = -1; YaxisMax = AxisScale;
                    break;
                case 2:
                    XaxisMin = -AxisScale; XaxisMax = 1;
                    YaxisMin = -1; YaxisMax = AxisScale;
                    break;
                case 3:
                    XaxisMin = -AxisScale; XaxisMax = 1;
                    YaxisMin = -AxisScale; YaxisMax = 1;
                    break;
                case 4:
                    XaxisMin = -1; XaxisMax = AxisScale;
                    YaxisMin = -AxisScale; YaxisMax = 1;
                    break;
                default:
                    break;

            }

            // Make the Y axis scale red
            //myPane.YAxis.Scale.FontSpec.FontColor = Color.Red;
            //myPane.YAxis.Title.FontSpec.FontColor = Color.Red;
            myPane.YAxis.Scale.Min = YaxisMin;
            myPane.YAxis.Scale.Max = YaxisMax;
            // Make the X axis scale blue
            //myPane.XAxis.Scale.FontSpec.FontColor = Color.Blue;
            //myPane.XAxis.Title.FontSpec.FontColor = Color.Blue;
            myPane.XAxis.Scale.Min = XaxisMin;
            myPane.XAxis.Scale.Max = XaxisMax;

            //the Start point and End point of the interpolation 
            list.Add(0, 0);
            LineItem myCurve = myPane.AddCurve("", list, Color.Red, SymbolType.Default);
            myCurve.Line.Width = 2;

            PointPairList listYscale = new PointPairList();
            for (int i = YaxisMin; i <= YaxisMax; i++)
                listYscale.Add(0, i);
            LineItem lineY = myPane.AddCurve("", listYscale, Color.Black, SymbolType.None);
            lineY.Line.Width = 1;

            PointPairList listAim = new PointPairList();
            listAim.Add(0, 0);
            listAim.Add(EndX, EndY);
            LineItem lineAim = myPane.AddCurve("", listAim, Color.Blue, SymbolType.None);
            lineAim.Line.Width = 1;

            // Tell ZedGraph to calculate the axis ranges
            // Note that you MUST call this after enabling IsAutoScrollRange, since AxisChange() sets
            // up the proper scrolling parameters
            zedGraphControl1.AxisChange();
            // Make sure the Graph gets redrawn
            zedGraphControl1.Invalidate();
        }
    }
}
